package com.robertux.leaderboard.util.gestoresModelos;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.List;
import java.util.Properties;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;

import org.apache.log4j.Logger;

import com.robertux.leaderboard.util.ResourceLocator;

public class GestorEntidades<T> {
	public static final String LEADERBOARD_PU = "LeaderboardPU";
	public static final String LEADERBOARD_JNDI = "java:comp/env/jdbc/LeaderboardDB";
	protected Logger logger;
	private EntityManager eMgr;

	public GestorEntidades() {
		this.logger = Logger.getLogger(this.getClass());
	}
	
	public GestorEntidades(EntityManager eMgr) {
		this();
		this.eMgr = eMgr;
	}
	
	public List<T> getEntidades(String nombre, Class<T> tipo) {
		return this.getEntityManager().createQuery("SELECT obj FROM " + nombre + " obj", tipo).getResultList();
	}
	
	public T getEntidad(String nombre, Class<T> tipo, long id) {
		TypedQuery<T> qry = this.getEntityManager().createQuery("SELECT obj FROM " + nombre + " obj WHERE obj.id = :id", tipo);
		qry.setParameter("id", id);
		try {
			return qry.getSingleResult();
		} catch (NoResultException nrE) {
			return null;
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar la entidad: " + e.getMessage(), e);
			return null;
		}
	}
	
	public void persistir(T obj) {
		this.getEntityManager().getTransaction().begin();
		this.getEntityManager().persist(obj);
		this.getEntityManager().getTransaction().commit();
	}
	
	public T actualizar(T obj) {
		this.getEntityManager().getTransaction().begin();
		T updated = this.getEntityManager().merge(obj);
		this.getEntityManager().getTransaction().commit();
		
		return updated;
	}
	
	public void refrescar(T obj) {
		this.getEntityManager().refresh(obj);
	}
	
	public void eliminar(T obj) {
		this.getEntityManager().getTransaction().begin();
		this.getEntityManager().remove(this.getEntityManager().merge(obj));
		this.getEntityManager().getTransaction().commit();
	}
	
	public EntityManager getEntityManager() {
		if(this.eMgr == null) {
			this.eMgr = getNewEntityManager();
		}
		
		return this.eMgr;
	}
	
	public EntityManager getNewEntityManager() {
		return Persistence.createEntityManagerFactory(LEADERBOARD_PU).createEntityManager();
	}
	
	public EntityManager getEntityManager(Properties props) {
		if(this.eMgr == null) {
			this.eMgr = getNewEntityManager(props);
		}
		
		return this.eMgr;
	}
	
	public EntityManager getNewEntityManager(Properties props) {
		return Persistence.createEntityManagerFactory(LEADERBOARD_PU, props).createEntityManager();
	}
	
	public Connection getConnection() {
		return ResourceLocator.dataSourceLookup(LEADERBOARD_JNDI);
	}
	
	public Connection getConnection(Properties props) {
		if(props == null) {
			return this.getConnection();
		} else {
			try {
				Class.forName(props.getProperty("javax.persistence.jdbc.driver"));
				return DriverManager.getConnection(props.getProperty("javax.persistence.jdbc.url"), 
						props.getProperty("javax.persistence.jdbc.user"), 
						props.getProperty("javax.persistence.jdbc.password"));
				
			} catch (Exception e) {
				this.logger.error("Error tratando de crear una conexión al SQL Server: " + e.getMessage(), e);
				return null;
			}
		}
	}
}
